/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package model;


import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;


/**
 *
 * @author Lazar
 */
public class Formula {
    
    private int xValue;
    private double yValue;
    private String formula;
    private double yConatainer; // promenljiva koja cuva vrednost u jednoj for iteraciji
    String regex;
    
    

    
    
    

    public void setFormula(String formula) {
        this.formula = formula;
    }

    public String getFormula() {
        return formula;
    }

    public double getyValue() {
        return yValue;
    }

    public void setyValue(int yValue) {
        this.yValue = yValue;
    }
    
    //metode za racunanje osnovnih f-ja. 
    //stepenovanje ne postoji, jer mi je lakse
    //da racunam "na licu mesta"
    public double calculateAbsolute (double x) {
       double absX = Math.abs(x);
       return absX;
    }   
    public double calculateSquareRoot (double x) {
       double sqrtX = Math.sqrt(x);
       return sqrtX;
    }                                                           
    public double calculateCubeRoot (double x) {
        double cbrtX = Math.cbrt(x);
        return cbrtX;
    }  
    public double calculateExp (double x) {
        double expX = Math.exp(x);
        return expX;
    }   
    public double calculateLn (double x) {
        double lnX = Math.log(x);
        return lnX;
    }    
    public double calculateLg (double x) {
        double lgX = Math.log10(x);
        return lgX;
    }    
    public double calculateSin (double x) {
        double sinX = Math.sin(x);
        return sinX;
    }    
    public double calculateCos (double x) {
        double cosX = Math.cos(x);
        return cosX;
    }    
    public double calculateTg (double x) {
        double tgX = Math.tan(x);
        return tgX;
    }    
    public double calculateCtg (double x) {
        double ctgX = 1/Math.tan(x);
        return ctgX;
    }    
    public double calculateArcsin (double x) {
        double arcsinX = Math.asin(x);
        return arcsinX;
    }    
    public double calculateArccos (double x) {
        double arccosX = Math.acos(x);
        return arccosX;
    }    
    public double calculateArctg(double x) {
        double arctgX = Math.atan(x);
        return arctgX;
    }    
    public double calculateArcctg (double x) {
        double arcctgX = 1/Math.atan(x);
        return arcctgX;
    }
    
    public void calculateYValue (double  x) { //funkcije proverava redosledom njihovih metoda za izracunavanje
      
      try {
          
        ScriptEngineManager mgr = new ScriptEngineManager();
        ScriptEngine engine = mgr.getEngineByName("JavaScript");
          
        String yString = engine.eval(formula.replace("x", x+"")).toString();
        
      
        
        for (int i = 0; i < formula.length(); i++) {                 
            
            if (formula.charAt(i) == '|') { // ako nije i+1 = formula.length, nije ni i, a meni i+1 treba za sledecu liniju
                int second = formula.indexOf('|', i+1); // ovo bi trebalo da cuva indeks prve sledece uspravne zagrade
                
                
                String izraz = formula.substring(i+1, second); //izraz izmedju dve uspravne zagrade

                try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza); //vrednost izraza unutar zagrada
                yConatainer = calculateAbsolute(vrednostIzrazaDouble); //vrednost izraza posle izvresnja funkcije nad njim
                    if (second != formula.length()){		
                    regex = formula.substring(i, second+1); 

                }else{
		String regex = formula.substring(i, second) + formula.charAt(second);
		}
                formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString(); //menja celu zagradu njenom vrednoscu

                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
        
            }
            
            else if (formula.charAt(i) == '^') { // za stepenovanje
                int argument =  Integer.parseInt(formula.valueOf(formula.charAt(i+1))); // u ovo nisam siguran
                yConatainer = Math.pow(x, argument);
                regex = formula.substring(i-1, i+2); //recimo x^4+..., ako je i na kapi, treba mi od x-a do +-a
                try {                                //ovde ne stavljam if-else, jer kapica na poslednjem mestu ne bi imala smisla
                   formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                } catch (ScriptException e) {
                    System.out.println(e.getMessage());
                }
            }
            
            else if (formula.substring(i).startsWith("e^")) {
                String izraz = formula.substring(formula.indexOf("(")+1, formula.indexOf(")")); //+1 zbog definicije substringa
                yConatainer = calculateExp(Double.parseDouble(izraz));
                regex = formula.substring(i, formula.indexOf(")")+1);
               
                try {
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                } catch (ScriptException e) {
                    System.out.println(e.getMessage());
                }
            }
            
            else if (formula.substring(i).startsWith("ln")) {
                String izraz = formula.substring(formula.indexOf("(")+1, formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateLn(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
           else if (formula.substring(i).startsWith("lg")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateLg(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
           else  if (formula.substring(i).startsWith("sin")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateSin(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
           else if (formula.substring(i).startsWith("cos")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateCos(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
            else if (formula.substring(i).startsWith("tg")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateTg(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
            else if (formula.substring(i).startsWith("ctg")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateCtg(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
            else if (formula.substring(i).startsWith("arcsin")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateArcsin(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
            else if (formula.substring(i).startsWith("arccos")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateArccos(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
            else if (formula.substring(i).startsWith("arctg")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateArctg(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            }
            
            else if (formula.substring(i).startsWith("arcctg")) {
                String izraz = formula.substring(formula.indexOf("("), formula.indexOf(")"));
                
                 try {
                String vrednostIzraza = engine.eval(izraz).toString();
            
                Double vrednostIzrazaDouble = Double.parseDouble(vrednostIzraza);
                    yConatainer = calculateArcctg(vrednostIzrazaDouble);
                    regex = formula.substring(i, formula.indexOf(")")+1);
                    formula = engine.eval(formula.replaceFirst(regex, yConatainer+"")).toString();
                }catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                
            } /*
               else { //ako nije nista od if-ova gore, mora biti polinom:
               LinkedList <Character> polinomElementi = new LinkedList <Character>(); //ako pretpostavimo da polinom ne moze imati vise od 50 znakova
               int indexPetlje = i; //tu je samo da ne bih menjao "i" iz fora u while-u ispod
               int mestoUListi = 0;
               
               while (formula.charAt(i) != '|' ||   //ako dodje do apsolutne zagrade
                        formula.charAt(i) != 's' ||     //ako dodje do sinusa
                            formula.charAt(i) != 'c' ||     //ako dodje do cos ili ctg
                               formula.charAt(i) != 't' ||      // ako dodje do tg
                                   formula.charAt(i) != 'a' ||      //ako dodje do nekog arcusa
                                       formula.charAt(i) != 'l' ||      //ako dodje do logaritma
                                           formula.charAt(i) != 'e' ||      //ako dodje do e^x
                                               formula.charAt(i+1) != '^') {     //ako dodje do stepenovanja
               
                   
                polinomElementi.add(formula.charAt(i));
                mestoUListi++;
               }
               
               char [] polinomElementiNiz = new char [50];
               
               for (int j = 0; j < polinomElementi.size()-1; j++) { //polinomElementi.size()-1 jer ce poslendnji
                                                                    //znak u listi biti neki operator, a to ne treba
                                                                    //u polinomu
                
                   polinomElementiNiz [j] = (char)(polinomElementi.get(j)); //prebacuje listu u niz da bih mogao od toga da napravim String
                                                                            //nisam siguran da li je cast dobar...
                   i=j; //da bi se for nastavio posle polinoma
               }
               
                                  
                String polinom = new String (polinomElementiNiz);
                   
                try {
                 String vrednostPolinoma = engine.eval(polinom).toString();
                 
                  Double vrednostIzrazaDouble = Double.parseDouble(vrednostPolinoma);
                        yConatainer = calculateLn(vrednostIzrazaDouble);
                 }catch (Exception e) {
                     System.out.println(e.getMessage());
                     }
               
            }
            */
            
            
            }
        yValue = Double.parseDouble(yString);

        } catch (Exception e) {
          System.out.println(e.getMessage());
      }
        
    }
      
    
    
}
